package com.zenithmind.gateway.filter;

import com.zenithmind.common.security.JwtUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Map;

import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;

@Component
public class LoggingGlobalFilter implements GlobalFilter, Ordered {

    private static final Logger logger = LoggerFactory.getLogger(LoggingGlobalFilter.class);

    /**
     * 自定义网关过滤器，用于处理进入网关的每个请求
     * 该方法的主要作用是记录请求的基本信息、处理时间以及请求结果
     *
     * @param exchange 服务器Web交换对象，包含请求和响应的所有信息
     * @param chain 网关过滤器链，用于执行下一个过滤器或最终的路由处理
     * @return Mono<Void> 表示异步处理完成的信号
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 记录请求开始时间
        long startTime = System.currentTimeMillis();
        
        // 获取当前请求
        ServerHttpRequest request = exchange.getRequest();
        
        // 提取请求路径
        String requestPath = request.getURI().getPath();
        
        // 提取请求方法
        String requestMethod = request.getMethod().name();
        
        // 获取请求发起者远程地址
        String remoteAddress = request.getRemoteAddress().getHostString();

        // 获取路由信息
        Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
        String targetService = route != null ? route.getId() : "unknown";

        // 获取JWT令牌中的用户信息（如果有）
        String userId = extractUserId(request);
        String username = extractUsername(request);

        // 记录收到请求的信息
        logger.info("收到请求 [{}] {} 来自 {}, 目标服务: {}, 用户: {}",
                requestMethod, requestPath, remoteAddress, targetService,
                userId != null ? userId : "匿名");

        // 记录查询参数
        if (request.getQueryParams() != null && !request.getQueryParams().isEmpty()) {
            logger.debug("请求参数: {}", request.getQueryParams());
        }

        // 直接处理请求，不读取请求体（避免复杂性）
        return processRequest(exchange, chain, startTime, requestMethod, requestPath,
                            remoteAddress, targetService, userId, username);
    }

    /**
     * 处理请求并记录响应信息
     */
    private Mono<Void> processRequest(ServerWebExchange exchange,
                                      GatewayFilterChain chain,
                                      long startTime,
                                      String requestMethod,
                                      String requestPath,
                                      String remoteAddress,
                                      String targetService,
                                      String userId,
                                      String username) {

        return chain.filter(exchange)
                .doOnSuccess(aVoid -> {
                    // 计算请求耗时
                    long executionTime = System.currentTimeMillis() - startTime;

                    // 获取响应状态码
                    int statusCode = exchange.getResponse().getStatusCode() != null ?
                            exchange.getResponse().getStatusCode().value() : 200;

                    // 记录完成请求的信息
                    logger.info("完成请求 [{}] {} 状态码: {} 耗时: {}ms 用户: {} 目标服务: {}",
                            requestMethod, requestPath, statusCode, executionTime,
                            userId != null ? userId : "匿名", targetService);
                })
                .doOnError(throwable -> {
                    // 计算请求耗时
                    long executionTime = System.currentTimeMillis() - startTime;

                    // 记录请求错误信息
                    logger.error("请求错误 [{}] {} 错误: {} 耗时: {}ms 用户: {} 目标服务: {}",
                            requestMethod, requestPath, throwable.getMessage(), executionTime,
                            userId != null ? userId : "匿名", targetService);
                });
    }

    /**
     * 从请求头中提取用户ID
     */
    private String extractUserId(ServerHttpRequest request) {
        try {
            String token = extractToken(request);
            if (token != null) {
                Map<String, Object> claims = JwtUtils.parseToken(token);
                return JwtUtils.extractUserIdFromClaims(claims);
            }
        } catch (Exception e) {
            logger.debug("提取用户ID失败", e);
        }
        return null;
    }

    /**
     * 从请求头中提取用户名
     */
    private String extractUsername(ServerHttpRequest request) {
        try {
            String token = extractToken(request);
            if (token != null) {
                Map<String, Object> claims = JwtUtils.parseToken(token);
                return JwtUtils.extractUsernameFromClaims(claims);
            }
        } catch (Exception e) {
            logger.debug("提取用户名失败", e);
        }
        return null;
    }

    /**
     * 从请求头中提取JWT令牌
     */
    private String extractToken(ServerHttpRequest request) {
        String authHeader = request.getHeaders().getFirst("Authorization");
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            return authHeader.substring(7);
        }

        // 也尝试从token头获取
        String token = request.getHeaders().getFirst("token");
        if (token != null && token.startsWith("ZenithMind ")) {
            return token.substring(11);
        }

        return token;
    }

    /**
     * 获取当前过滤器的优先级顺序
     *
     * 返回值为-1，表示该过滤器的优先级低于认证过滤器，确保在认证之前执行日志记录
     *
     * @return 返回过滤器的优先级顺序，值为-1
     */
    @Override
    public int getOrder() {
        return -1;  // 比认证过滤器优先级低，先执行日志记录
    }
} 